let types = require('../constants');
let commandModule = require('../modules/command-module');
let commandUtil = require('./command-util');
let nodeUtil = require('../common/node-util');

let operaCmdGenerator = {
  result: {},
  generate(node) {
    if (this.isShowExp(node)) {
      this.result = this.genShowCommand(node);
    } else {
      if (this.isUnary(node)) {
        this.result = this.genUnaryCommand(node);
      } else {
        this.result = this.genNormalCommand(node);
      }
    }
    return this.result;
  },
  isShowExp(node) {
    return !node.params;
  },
  isUnary(node) {
    return node.params.length == 0;
  },
  genUnaryCommand(node) {
    let value = node.operator.value;
    switch (value) {
      case types.COMMAND_KEYWORD.SAVE:
      case types.COMMAND_KEYWORD.UNDO:
      case types.COMMAND_KEYWORD.REDO:
        return new commandModule.GraphUnary(value);
      case types.COMMAND_KEYWORD.LIST:
      case types.COMMAND_KEYWORD.CLEAR:
        return new commandModule.ModuleUnary(value);
    }
  },
  genNormalCommand(node) {
    return node.params.map(param => {
      if (node.operator.value == types.COMMAND_KEYWORD.REMOVE) {
        if (nodeUtil.isNodeLiteral(param)) {
          let target = nodeUtil.getLiteralValue(param.value);
          if (target == types.NODE_IDENTIFIER.START) {
            return new commandModule.RmEdge(target);
          } else {
            return new commandModule.RmNode(target);
          }
        } else {
          let target = nodeUtil.getLiteralValue(param.left);
          let port = nodeUtil.getLiteralValue(param.right);
          return new commandModule.RmEdge(target, port);
        }
      } else if (node.operator.value == types.COMMAND_KEYWORD.CLONE) {
        let target = nodeUtil.getLiteralValue(param.left);
        let operaValue = param.operator.value;
        let refValue = nodeUtil.getLiteralValue(param.right);
        let pos = commandUtil.parsePosNode(operaValue, refValue);
        return new commandModule.Clone(target, pos);
      }
    });
  },
  genShowCommand(node) {
    if (nodeUtil.isNodeLiteral(node)) {
      let target = nodeUtil.getLiteralValue(node);
      return new commandModule.Show(target, types.PROPERTY_SCOPE.ALL);
    } else {
      let target = nodeUtil.getLiteralValue(node.left);
      let scope = nodeUtil.getShowCommandScope(node);
      let key = nodeUtil.getLiteralValue(node.right);
      return new commandModule.Show(target, scope, key);
    }
  }
};

module.exports = operaCmdGenerator;
